/*
 * $Id: JXTitledPanel.java 4147 2012-02-01 17:13:24Z kschaefe $
 *
 * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
 * Santa Clara, California 95054, U.S.A. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

package org.jdesktop.swingx;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Font;

import javax.swing.BorderFactory;
import javax.swing.JComponent;

import org.jdesktop.beans.JavaBean;
import org.jdesktop.swingx.painter.Painter;
import org.jdesktop.swingx.plaf.LookAndFeelAddons;
import org.jdesktop.swingx.plaf.TitledPanelAddon;
import org.jdesktop.swingx.plaf.TitledPanelUI;

/**
 * A special type of Panel that has a Title section and a Content section.<br>
 * The following properties can be set with the UIManager to change the look and
 * feel of the JXTitledPanel:
 * <ul>
 * <li>JXTitledPanel.titleForeground</li>
 * <li>JXTitledPanel.titleBackground</li>
 * <li>JXTitledPanel.titleFont</li>
 * <li>JXTitledPanel.titlePainter</li>
 * <li>JXTitledPanel.captionInsets</li>
 * <li>JXTitledPanel.rightDecorationInsets</li>
 * <li>JXTitledPanel.leftDecorationInsets</li>
 * </ul>
 * 
 * @author Richard Bair
 * @author Nicola Ken Barozzi
 * @author Jeanette Winzenburg
 */
@JavaBean
public class JXTitledPanel extends JXPanel {

	/**
	 * @see #getUIClassID // *
	 * @see #readObject
	 */
	static public final String uiClassID = "TitledPanelUI";

	public static final String LEFT_DECORATION = "JXTitledPanel.leftDecoration";

	public static final String RIGHT_DECORATION = "JXTitledPanel.rightDecoration";

	/**
	 * Initialization that would ideally be moved into various look and feel
	 * classes.
	 */
	static {
		LookAndFeelAddons.contribute(new TitledPanelAddon());
	}

	/**
	 * The text to use for the title
	 */
	private String title = "";

	/**
	 * The Font to use for the Title
	 */
	private Font titleFont;

	/**
	 * The foreground color to use for the Title (particularly for the text)
	 */
	private Color titleForeground;

	/**
	 * The ContentPanel. Whatever this container is will be displayed in the
	 * Content section
	 */
	private Container contentPanel;

	/**
	 * The Painter to use for painting the title section of the JXTitledPanel
	 */
	private Painter titlePainter;

	/**
	 * Create a new JTitledPanel with an empty string for the title.
	 */
	public JXTitledPanel() {
		this(" ");
	}

	/**
	 * Create a new JTitledPanel with the given title as the title for the
	 * panel.
	 * 
	 * @param title
	 */
	public JXTitledPanel(String title) {
		this(title, createDefaultContainer());
	}

	/**
	 * Create a new JTitledPanel with the given String as the title, and the
	 * given Container as the content panel.
	 * 
	 * @param title
	 * @param content
	 */
	public JXTitledPanel(String title, Container content) {
		setTitle(title);
		setContentContainer(content);
	}

	/**
	 * Returns the look and feel (L&F) object that renders this component.
	 * 
	 * @return the TitledPanelUI object that renders this component
	 */
	@Override
	public TitledPanelUI getUI() {
		return (TitledPanelUI) ui;
	}

	/**
	 * Sets the look and feel (L&F) object that renders this component.
	 * 
	 * @param ui
	 *            the TitledPanelUI L&F object
	 * @see javax.swing.UIDefaults#getUI
	 * @beaninfo bound: true hidden: true attribute: visualUpdate true
	 *           description: The UI object that implements the Component's
	 *           LookAndFeel.
	 */
	public void setUI(TitledPanelUI ui) {
		super.setUI(ui);
	}

	/**
	 * Returns a string that specifies the name of the L&F class that renders
	 * this component.
	 * 
	 * @return "TitledPanelUI"
	 * @see JComponent#getUIClassID
	 * @see javax.swing.UIDefaults#getUI
	 * @beaninfo expert: true description: A string that specifies the name of
	 *           the L&F class.
	 */
	@Override
	public String getUIClassID() {
		return uiClassID;
	}

	/**
	 * Notification from the <code>UIManager</code> that the L&F has changed.
	 * Replaces the current UI object with the latest version from the
	 * <code>UIManager</code>.
	 * 
	 * @see javax.swing.JComponent#updateUI
	 */
	@Override
	public void updateUI() {
		setUI((TitledPanelUI) LookAndFeelAddons.getUI(this, TitledPanelUI.class));
	}

	/**
	 * Gets the title for this titled panel.
	 * 
	 * @return the currently displayed title
	 */
	public String getTitle() {
		return title;
	}

	/**
	 * Sets the title for this title panel.
	 * 
	 * @param title
	 *            the title to display
	 */
	public void setTitle(String title) {
		String oldTitle = this.title;
		this.title = (title == null ? "" : title);
		// JW: fix swingx #9 - missing/incorrect notification
		// let standard notification handle
		// NOTE - "getting" the new property in the fire method is
		// intentional: there's no way of missing any transformations
		// on the parameter to set (like above: setting a
		// value depending on whether the input is null).
		firePropertyChange("title", oldTitle, getTitle());
	}

	public Container getContentContainer() {
		if (contentPanel == null) {
			contentPanel = new JXPanel();
			((JXPanel) contentPanel).setBorder(BorderFactory.createEmptyBorder());
			this.add(contentPanel, BorderLayout.CENTER);
		}
		return contentPanel;
	}

	public void setContentContainer(Container contentPanel) {
		if (this.contentPanel != null) {
			remove(this.contentPanel);
		}
		add(contentPanel, BorderLayout.CENTER);
		this.contentPanel = contentPanel;
	}

	/**
	 * Adds the given JComponent as a decoration on the right of the title
	 * 
	 * @param decoration
	 */
	public void setRightDecoration(JComponent decoration) {
		JComponent old = getRightDecoration();
		getUI().setRightDecoration(decoration);
		firePropertyChange("rightDecoration", old, getRightDecoration());
	}

	public JComponent getRightDecoration() {
		return getUI().getRightDecoration();
	}

	/**
	 * Adds the given JComponent as a decoration on the left of the title
	 * 
	 * @param decoration
	 */
	public void setLeftDecoration(JComponent decoration) {
		JComponent old = getLeftDecoration();
		getUI().setLeftDecoration(decoration);
		firePropertyChange("leftDecoration", old, getLeftDecoration());
	}

	public JComponent getLeftDecoration() {
		return getUI().getLeftDecoration();
	}

	public Font getTitleFont() {
		return titleFont;
	}

	public void setTitleFont(Font titleFont) {
		Font old = getTitleFont();
		this.titleFont = titleFont;
		firePropertyChange("titleFont", old, getTitleFont());
	}

	/**
	 * Set the Painter to use for painting the title section of the
	 * JXTitledPanel. This value may be null, which will cause the current look
	 * and feel to paint an appropriate look
	 *
	 * @param p
	 *            The Painter to use. May be null
	 */
	public void setTitlePainter(Painter p) {
		Painter old = getTitlePainter();
		this.titlePainter = p;
		firePropertyChange("titlePainter", old, getTitlePainter());
	}

	/**
	 * @return the Painter to use for painting the background of the title
	 *         section
	 */
	public Painter getTitlePainter() {
		return titlePainter;
	}

	public Color getTitleForeground() {
		return titleForeground;
	}

	public void setTitleForeground(Color titleForeground) {
		Color old = getTitleForeground();
		this.titleForeground = titleForeground;
		firePropertyChange("titleForeground", old, getTitleForeground());
	}

	private static Container createDefaultContainer() {
		// TODO: All this default container creation stuff should be in the UI
		// delegate. Not enough time at the moment for me to do this right.
		JXPanel p = new JXPanel();
		p.setOpaque(false);
		return p;
	}

}
